
use serde::Serialize;

#[derive(Debug)]
#[derive(Serialize)]
enum ResponseResultType
{
    Success,
    Failed
}


#[derive(Debug)]
#[derive(Serialize)]
pub struct ResponseResult<T>
    where T: Serialize + Send
{
    r#type: ResponseResultType,
    time: chrono::DateTime<chrono::Local>,
    message: String,
    data: T
}


impl <T> ResponseResult<T>
    where T: Serialize + Send
{
    fn new(r#type: ResponseResultType, time: chrono::DateTime<chrono::Local>, message: String, data: T) -> Self
    {
        Self {
            r#type,
            time,
            message,
            data
        }
    }


    pub fn success(message: String, data: T) -> Self
    {
        Self::new(
            ResponseResultType::Success,
            chrono::Local::now(),
            message,
            data
        )
    }


    pub fn failed(message: String, data: T) -> Self
    {
        Self::new(
            ResponseResultType::Failed,
            chrono::Local::now(),
            message,
            data
        )
    }

}


#[derive(Debug)]
enum ResponseErrorKind
{
    NotFound,               // 404
    PermissionDenied,       // 401，没有权限
    InternalServerError,    // 500，服务器内部错误
    JsonParseError,         // 解析错误
    DatabaseError,          // 数据库错误
}


#[derive(Debug)]
pub struct ResponseError
{
    kind: ResponseErrorKind,
    message: String
}

impl ResponseError
{
    fn new(kind: ResponseErrorKind, message: String) -> Self
    {
        Self {
            kind,
            message
        }
    }

    pub fn not_found() -> Self
    {
        Self::new(
            ResponseErrorKind::NotFound,
            "NotFound".to_string()
        )
    }

    pub fn permission_denied() -> Self
    {
        Self::new(
            ResponseErrorKind::PermissionDenied,
            "没有权限".to_string()
        )
    }

    pub fn internal_server_error(message: String) -> Self
    {
        Self::new(
            ResponseErrorKind::InternalServerError,
            message
        )
    }

    pub fn json_parse_error(message: String) -> Self
    {
        Self::new(
            ResponseErrorKind::JsonParseError,
            message
        )
    }

    pub fn database_error() -> Self
    {
        Self::new(
            ResponseErrorKind::DatabaseError,
            "数据库错误".to_string()
        )
    }
}



#[salvo::async_trait]
impl <T> salvo::Writer for ResponseResult<T>
    where T: Serialize + Send
{
    async fn write(mut self, req: &mut salvo::Request, depot: &mut salvo::Depot, res: &mut salvo::Response)
    {
        let sr = serde_json::to_string(&self);
        if sr.is_err()
        {
            let err = ResponseError::internal_server_error("返回值序列化失败".to_string());
            err.write(req, depot, res).await;
            return;
        }

        let mut headers = salvo::hyper::HeaderMap::new();
        headers.append(
            "ContentType",
            salvo::http::HeaderValue::from_str("application/json;charset=utf-8")
                .unwrap()
        );
        res.set_headers(headers);
        res.render(sr.unwrap());
    }
}



#[salvo::async_trait]
impl salvo::Writer for ResponseError
{
    async fn write(mut self, _req: &mut salvo::Request, _depot: &mut salvo::Depot, res: &mut salvo::Response)
    {
        match self.kind {
            ResponseErrorKind::NotFound => 
                res.status_code(salvo::prelude::StatusCode::NOT_FOUND),
            ResponseErrorKind::PermissionDenied => 
                res.status_code(salvo::prelude::StatusCode::UNAUTHORIZED),
            ResponseErrorKind::InternalServerError =>
            res.status_code(salvo::prelude::StatusCode::INTERNAL_SERVER_ERROR),
            ResponseErrorKind::JsonParseError =>
                res.status_code(salvo::prelude::StatusCode::BAD_REQUEST),
            ResponseErrorKind::DatabaseError =>
                res.status_code(salvo::prelude::StatusCode::INTERNAL_SERVER_ERROR)
        };
        
        res.render(self.message);
    }
}




pub type WebResult<T> = Result<ResponseResult<T>, ResponseError>;




